/*
 * Partida.h
 *
 *  Created on: 28/06/2014
 *      Author: loreyalan
 */

#ifndef PARTIDA_H_
#define PARTIDA_H_

#include <stdio.h>
#include <string.h>
#include <string>
#include <stdlib.h>
#include <queue>
#include "cstdlib"
#include <unistd.h>
#include <cstdio>
#include <sys/types.h>
#include <string>
#include <iostream>
#include <dirent.h>
#include <sys/stat.h>
#include <list>
#include <utility>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_video.h>
#include <map>
#include <sstream>
#include "ctime"
#include "Protocolo.h"
#include "ThreadMutex.h"
#include "ComandoServidor.h"
#include "Config.h"
//Comandos
#include "ComandoServidor.h"
#include "ComandoMover.h"
#include "ComandoReparar.h"
#include "ComandoCrearAve.h"
#include "ComandoCrearLadrillo.h"
#include "ComandoCrearTorta.h"
#include "ComandoDeleteAve.h"
#include "ComandoDeleteLadrillo.h"
#include "ComandoDeleteTorta.h"
#include "ComandoLanzarLadrillo.h"
#include "ComandoFinTramo.h"
#include "ComandoFinNivel.h"
#include "ComandoFinPartida.h"
#include "ComandoActRanking.h"
#include "ComandoInitNivel.h"
#include "ComandoInitTramo.h"
#include "ComandoInitPartida.h"
#include "ComandoComenzar.h"
#include "ComandoSalirJuego.h"
#include "ComandoActualizarPuntaje.h"
#include "ComandoConsumirTorta.h"
#include "ComandoRestarVida.h"
#include "ComandoMorir.h"
#include "ComandoFinTorneo.h"
#include "map"

class Partida {
private:
	/* Cosas del display */

	//Imagen para fondo+vidrios+bloqueos
	SDL_Surface *pantallaBase;

	 //Imagen sprites Felix1
	SDL_Surface *imagen1;

	//Imagen sprites Felix1
	SDL_Surface *imagen2;

	/* Matriz del video */
	destinoSprite matriz[53][10];

	/* DAtos de la partida*/
	unsigned short int miIdJugador;
	string miNombre;
	int tramo;
	map<int,int> *controles;

	/* Indica si estoy vivo */
	bool estoyVivo;

    /* Mutex para la modificacion o acceso de la pantalla */
    ThreadMutex *mutexPantalla;

    /* --------------------------------------------------------------------*/

	/* Instancia del interprete. */
    static Partida *instance;

    /* Indicador de actividad */
    bool activo;
    bool finTorneo;
    bool stoped;
    bool finError;

	/* Colas de salidas a los jugadores 1 y 2 para que procesen los cambios. */
	queue<t_accion> colaAccionesAEnviar;

	/* Cola de t_acciones a ejecutar. */
	queue<t_accion> colaAccionesAEjecutar;

	//Mutex para recursos criticos.
	ThreadMutex	*mutexColaAccionesAEjecutar;	//Para uso exclusivo de la cola
	ThreadMutex	*mutexColaAccionesAEnviar;		//Para uso exclusivo de la cola
	ThreadMutex	*mutexHayQueEjecutar;			//Para saber si hay respuestas a enviar.
	ThreadMutex	*mutexHayQueEnviar;  			//Para saber si hay t_acciones a procesar.

public:
	/* COnstructores y destructores */
	Partida();
	virtual ~Partida();

	/* Getters */
	bool isActivo();
	bool isStoped();
	bool isFinError();
	static Partida *getInstance();
	bool isFinTorneo();
	string getRankingJugador();

	/* Setters */
	void setMiNombre(char *miNombre);
	void setControles(map<int, int> *controles);
	void setPantallaBase(SDL_Surface *pantallaBase);
	void setImagen1(SDL_Surface *imagen1);
	void setImagen2(SDL_Surface *imagen2);
	void setStoped(bool stoped);
	void setActivo(bool activo);

	/* Funcionalidades de la partida */


	/* Recibe las teclas ingresadas por el jugador y genera las acciones a encolar pertinenetes */
	t_accion getTeclaPresionada();
	/* Funcion que ejecuta la actualizacion de la informacion en la pantalla */
	void refreshDisplay();
	/* Metodo que ejecuta las acciones iniciales de la partida y del display, antes de recibir acciones del servidor*/
	void iniciarPartida();

	/* Manipulacion de colas */

	/* Encola una accion para impactar en la pantalla */
	void encolarAccionAEjecutar(t_accion action);
	/* Va sacando de la cola las acciones a ejecutar en la pantalla para ejecutarla */
	t_accion desencolarAccionAEjecutar();
	/* Encola una accion para impactar en la pantalla */
	void encolarAccionAEnviar(t_accion action);
	/* Va sacando de la cola las acciones a ejecutar en la pantalla para ejecutarla */
	t_accion desencolarAccionAEnviar();
	/* Procesa el siguiente evento en la cola de t_acciones a procesar. */
	void procesarAccion();
	/* Funcion que toma el proximo ingreso de tecla y lo encola para ser procesaro por el servidor */
	void tomarAccionPresionada();

	/* Acciones */
	/* Metodo para realizar la t_accion de mover ingresada por parametro, primero valida. */
	int move(t_accion *action);
	/* Metodo de reparacion de una ventana. */
	bool reparar(t_accion *action);
	/* Activa un objeto ave y le asigna el x y solicitado en la accion recibida. */
	bool crearAve(t_accion *action);
	/* Activa una torta  y le asigna el vidrio solicitado en la accion recibida. */
	bool crearTorta(t_accion *action);
	/* Activa un ladrillo del stock de ladrillos libres en la posicion donde lo indica la accion */
	bool crearLadrillo(t_accion *action);
	/* Metodo para eliminar un ave */
	bool deleteAve(t_accion *action);
	/* Metodo para eliminar un ladrillo */
	bool deleteLadrillo(t_accion *action);
	/* Metodo para eliminar un torta */
	bool deleteTorta(t_accion *action);
	/* Metodo para la accion ACC_CONSUMIR_TORTA, da inmunidad al Felix indicado en id_entidad */
	bool consumirTorta(t_accion *action);
	/* Ejecuta la accion de lanzado de un ladrillo para ralph. */
	bool lanzarLadrillo(t_accion *action);
	/* Ejecuta la accion de quitar a un jugador del juego y de la partida */
	bool salirDelJuego(t_accion *action);
	//Pasa al siguiente tramo.
	bool finalizarTramo(t_accion *action);
	//Pasa al siguiente nivel.
	bool finalizarNivel(t_accion *action);
	/* Termina el torneo esperando a que finalice la partida para salir */
	bool finalizarTorneo(t_accion *action);
	//Termina la partida.
	bool finalizarPartida(t_accion *action);
	/* Inicia la partida en el juego */
	bool inicializarPartida(t_accion *action);
	/* Metodo que inicializa el nivel en la pantalla del jugador */
	void inicializarNivel(t_accion *accion);
	/* Metodo que inicializa el tramo en la pantalla del jugador */
	void inicializarTramo(t_accion *accion);
	/* Actualiza el ranking de los jugadores */
	bool actualizarRanking(t_accion *accion) ;
	/* Inicia el juego */
	bool start(t_accion *action);
	/* Actualiza el puntaje */
	bool actualizarPuntaje(t_accion *accion);

	// Decremento las vidas del jugador ///////////////////////////
	void decrementarVidas(unsigned char *vidas);
	/* Felix pierde una vida */
	bool restarVida(t_accion *action);
	/* Felix perdio las 3 vidas */
	bool perderPartida(t_accion *action);

	/* Cosas del display */
	void vaciarMatriz();
	/* Metodo que actualiza la pantalla con los cambios */
	void refresh();
	// Cargo el nombre del Jugador en la matriz //////////////////////////
	void cargarNombre(string nombre, unsigned short int jugador);
	// Cargo el puntaje del Jugador en la matriz //////////////////////////
	void cargarPuntaje(string punt, unsigned short int jugador);


	/* Sortea los vidrios rotos de la partida */
	void sortearVidrios(t_accion *accion);
	/* Cargo estado de los bloqueos en la matriz */
	void sortearBloqueos(t_accion *accion);
	/* Sortea el estado del bloqueo */
	char sortearEstadoBloqueo(int i, char tipoBloqueo);
	/* Quita aleatoriamente la cantidad de bloqueos por fila o columna ingresada por parámetro. */
	void quitarBloqueosParaJugar(char tipoBloqueo, t_accion *accion);
	/* Quita un bloqueo horizontal al azar. */
	void quitarBloqueoHorizontal(char tipoBloqueo, t_accion *accion);
	/* Quita un bloqueo vertical al azar. */
	void quitarBloqueoVertical(char tipoBloqueo, t_accion *accion);
	/* Trae los idEntidad base para offsetear y obtener los id de los bloqueos buscados. */
	short int getIdBaseBloqueo(char tipoBloqueo, int fila);
	// Obtengo el puntaje del jugador ////////////////////////////
	string obtenerPuntaje(unsigned short int jugador);
	// Cargo las vidas del Jugador en la matriz //////////////////////////
	void cargarVidas(unsigned char vidas, unsigned short int jugador);
	// Obtengo las vidas del jugador ////////////////////////////
	unsigned char obtenerVidas(unsigned short int jugador);
	/* Convierte un idimagen de numero en una constante */
	unsigned int obtenerNumero(unsigned char letra);
	/* Obtengo el numero de nivel actual*/
	unsigned int obtenerNivel();
	////////// Devuelve la coordenada de un sprite dentro de la imagen //////////////////////
	SDL_Rect obtenerOrigenSprite(unsigned char nombre);
	/* Metodo que interpreta el evento SDL_Event de teclado */
	t_accion procesarEventoSDLKeyDown(SDL_Event *event);
};

#endif /* PARTIDA_H_ */
